package com.zeus.base.smscenter.schedule.task;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.smscenter.server.core.IExecutor;
import com.smscenter.server.core.tradingcenter.TradingConsumExecutor;
import com.smscenter.server.core.vcomcn.VComQuery;
import com.zeus.base.privilege.model.TbUser;
import com.zeus.base.privilege.service.IUserService;
import com.zeus.base.privilege.utils.ArithUtil;
import com.zeus.base.privilege.utils.DateUtil;
import com.zeus.base.privilege.utils.ResultModel;
import com.zeus.base.smscenter.common.constant.SmsConstants;
import com.zeus.base.smscenter.common.util.StringUtils;
import com.zeus.base.smscenter.model.SmsLogInfo;
import com.zeus.base.smscenter.model.SmsSupplierProperty;
import com.zeus.base.smscenter.service.ISmsLogInfoService;
import com.zeus.base.smscenter.service.ISupplierPropertyService;
import com.zeus.base.tradingcenter.service.IConsumeDetailService;
import com.zeus.base.tradingcenter.service.IConsumeTypeService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by ShanFei on 2017-04-07.
 */
@Component
public class ScheduledTasks {
    //各种定时器使用 http://blog.csdn.net/applebomb/article/details/52400154

    private static final Logger LOG = Logger.getLogger(ScheduledTasks.class);
    @Autowired
    private ISmsLogInfoService smsLogInfoService;
    @Autowired
    private ISupplierPropertyService smsSupplierPropertyService;
    @Autowired
    private IConsumeTypeService iConsumeTypeService;
    @Autowired
    private IConsumeDetailService iConsumeDetailService;
    @Autowired
    private IUserService iUserService;

    /**
     * 1平台(集时通)语音短信状态报告查询并重新计算费用
     *
     * 现将交易记录如下.tradingNo为交易平台单号,也是传给短信运营商唯一编号,故不可变动
     * 将重新计费单号保存至交易备注里,以备用,
     * 等将短信全部合并后,将表字段重新设计,明确作用
     */
    @Scheduled(fixedRate = 1000*60)   //挨着执行执行任务占用间隔时间 但不并发
    public void voiceSmsResult() throws InterruptedException {
        HashMap<String,Object> param = new HashMap<String,Object>();
        param.put("sendType","VOICE");
        param.put("supplierChannel","1");
        param.put("status","SUCCESS");
        param.put("outResponseMessage","SUCCESS");
        param.put("isSynchroIsNull","true");
        param.put("tradingNoIsNotNull","true");
        param.put("startIndex",0);
        param.put("pageSize",500);
        List<SmsLogInfo> list = smsLogInfoService.findListByCondition(param);
        if(list != null && list.size() > 0){
            VComQuery query = new VComQuery();
            for(int i=0;i<list.size();i++){
                try {
                    SmsLogInfo sms = list.get(i);
                    LOG.error(sms.getId());
                    param.clear();
                    param.put("code", sms.getTenant());
                    param.put("supplierNo", sms.getSupplierChannel());
                    List<SmsSupplierProperty> smsSupplierPropertyList = smsSupplierPropertyService.find(param);
                    param.clear();
                    for (SmsSupplierProperty smsSupplierProperty : smsSupplierPropertyList) {
                        param.put(smsSupplierProperty.getPropertyName(), smsSupplierProperty.getPropertyValue());
                    }
                    HashMap map = new HashMap();
                    map.put("loginName", param.get("loginName"));//即时通fytest1 82557339
                    map.put("serviceType", "VOICE");
                    map.put("password", param.get("loginPassword"));
                    map.put("bizNo", sms.getTradingNo());
                    String s = query.querySendRecordInfo(map);
                    if("{}".equals(s)){//空的代表没有查询到
                        continue;
                    }
                    JSONObject json = JSONObject.parseObject(s);
                    int min = 0;
                    //{"state":"成功","duration":"5","phone":"015504607909","tradingNo":"2018020800001","charge":"180"}
                    sms.setIsSynchro("1");
                    if("成功".equals(json.getString("state")) || "总机通分机未通".equals(json.getString("state")) || "呼叫成功转热线失败".equals(json.getString("state"))){
                        //{"state":"成功","duration":"30","phone":"015504607909","tradingNo":"2018021000004","charge":"180"}
                        min = 1;
                        int time = Integer.parseInt(json.getString("duration"));
                        if(time>60){
                            //转换分钟
                            if(time % 60 == 0){
                                min = time / 60;
                            }else{
                                min = (time / 60) + 1;
                            }
                        }
                        sms.setOutResponseMessage("SUCCESS");
                        sms.setUseSmsCount(min);
//                        sms.setContentLength(time);//不更新,避免前端显示认为61为两条还是按字数来
                    }else{
                        sms.setOutResponseMessage(json.getString("state"));
                    }
                    Double amount = null;
                    try {
                        amount = Double.parseDouble(param.get("voiceUnitPrice") + "");
                    } catch (Exception e) {
                    }
                    if(amount == null || amount <= 0){//如果为空,或是负数,使用默认
                        amount = 0.18;
                    }
                    //将原有的扣费回冲
                    if (!StringUtils.isEmpty(sms.getAuthCenterUserName()) && !StringUtils.isEmpty(sms.getAuthCenterPassword())) {
                        TbUser user = iUserService.getUserByLoginName(sms.getAuthCenterUserName());
                        TradingConsumExecutor tradingExecutor = new TradingConsumExecutor();
                        ResultModel resultConsumRevert = tradingExecutor.excuteRevertConsume(sms.getTradingNo(), user, "语音短信计算真实消费回冲", iConsumeDetailService);
                        if(resultConsumRevert.isSuccess()){
                            sms.setTradingRemark(resultConsumRevert.getObject()+"");
                            sms.setLoadStatus("1");
                            sms.setAmount(new Double(ArithUtil.mul(ArithUtil.mul(amount , sms.getUseSmsCount()),100)).intValue());
                            smsLogInfoService.update(sms);
                            if("SUCCESS".equals(sms.getOutResponseMessage())){//实际消费扣费
                                ResultModel resultModelConsum = tradingExecutor.excuteConsume(SmsOnsMessageListener.getConsumeType("短信", iConsumeTypeService), ArithUtil.mul(amount , sms.getUseSmsCount()), user, iConsumeDetailService);
                                if(resultModelConsum.isSuccess()){
                                    sms.setTradingRemark(resultModelConsum.getObject()+"");
                                    sms.setLoadStatus("2");
                                    sms.setAmount(new Double(ArithUtil.mul(ArithUtil.mul(amount , sms.getUseSmsCount()),100)).intValue());
                                }
                                smsLogInfoService.update(sms);
                            }
                        }
                    }else{
                        sms.setAmount(new Double(ArithUtil.mul(ArithUtil.mul(amount , sms.getUseSmsCount()),100)).intValue());
                        smsLogInfoService.update(sms);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            LOG.error("本次更新======"+list.size());
        }

    }


    /**
     * 查询短信出现异常导致交易中心没有扣费的数据,进行补扣  暂没写完
     * @throws InterruptedException
     */
//    @Scheduled(fixedRate = 1000*30)   //挨着执行执行任务占用间隔时间 但不并发
//    public void updateSmsConsume() throws InterruptedException {
//        HashMap<String,Object> param = new HashMap<String,Object>();
//        param.put("LoadStatus","1");
//        param.put("status","SUCCESS");
//        param.put("outResponseMessage","SUCCESS");
//        param.put("isSynchro","1");
//        param.put("authCenterUserNameIsNotNull","true");
//        param.put("startIndex",0);
//        param.put("pageSize",500);
//        List<SmsLogInfo> list = smsLogInfoService.findListByCondition(param);
//        if(list != null && list.size() > 0){
//            VComQuery query = new VComQuery();
//            for(int i=0;i<list.size();i++){
//                try {
//                    SmsLogInfo sms = list.get(i);
//                    param.clear();
//                    param.put("code", sms.getTenant());
//                    param.put("supplierNo", sms.getSupplierChannel());
//                    List<SmsSupplierProperty> smsSupplierPropertyList = smsSupplierPropertyService.find(param);
//                    param.clear();
//                    for (SmsSupplierProperty smsSupplierProperty : smsSupplierPropertyList) {
//                        param.put(smsSupplierProperty.getPropertyName(), smsSupplierProperty.getPropertyValue());
//                    }
//                    int min = sms.getUseSmsCount();
//                    sms.setIsSynchro("2");
//                    Double amount = null;
//                    try {
//                        if("VOICE".equals(sms.getSendType())){
//                            amount = Double.parseDouble((String)param.get("voiceUnitPrice"));
//                        }else{
//                            amount = Double.parseDouble((String)param.get("unitPrice"));
//                        }
//                    } catch (Exception e) {
//                    }
//                    if(amount == null || amount <= 0){//如果为空,或是负数,使用默认
//                        if("VOICE".equals(sms.getSendType())){
//                            amount = 0.18;
//                        }else{
//                            amount = 0.1;
//                        }
//                    }
//
//
//
//
//
//
//
//
//
//                    //将原有的扣费回冲
//                    IExecutor tradingExecutor;
//                    Map<String,Object> tradRevertParams= Maps.newHashMap();
//                    tradRevertParams.put("userName", sms.getAuthCenterUserName());
//                    tradRevertParams.put("password", sms.getAuthCenterPassword());
//                    tradRevertParams.put("tradNo", sms.getTradingNo());
//                    tradRevertParams.put("companyCode", sms.getTenant());
//                    tradRevertParams.put("remark", "语音短信计算真实消费回冲");
//                    tradingExecutor = new TradingConsumRevertExecutor();
//                    String resultConsum = tradingExecutor.excute(tradRevertParams);
//                    ResultModel resultModelConsum = JSON.parseObject(resultConsum,ResultModel.class);
//                    if(resultModelConsum.isSuccess()){//判断回冲返回
//                        sms.setTradingRemark(resultModelConsum.getObject()+"");
//                        sms.setTradingNo("");
//                        sms.setLoadStatus("1");
//                        sms.setAmount(new Double(ArithUtil.mul(ArithUtil.mul(amount , sms.getUseSmsCount()),100)).intValue());
//                        smsLogInfoService.update(sms);
//                        if("SUCCESS".equals(sms.getOutResponseMessage())){//实际消费扣费
//                            Map<String,Object> tradParams= Maps.newHashMap();
//                            tradParams.put("userName", sms.getAuthCenterUserName());
//                            tradParams.put("password", sms.getAuthCenterPassword());
//                            tradParams.put("type", "短信");
//                            tradParams.put("money", ArithUtil.mul(amount , sms.getUseSmsCount()));
//                            tradParams.put("companyCode", sms.getTenant());
//                            tradParams.put("remark", "发送短信扣费");
//                            tradingExecutor = new TradingConsumExecutor();
//                            resultConsum = tradingExecutor.excute(tradParams);
//                            resultModelConsum = JSON.parseObject(resultConsum,ResultModel.class);
//                            if(resultModelConsum.isSuccess()){
//                                sms.setTradingNo(resultModelConsum.getObject()+"");
//                                sms.setLoadStatus("2");
//                                sms.setAmount(new Double(ArithUtil.mul(ArithUtil.mul(amount , sms.getUseSmsCount()),100)).intValue());
//                            }
//                            smsLogInfoService.update(sms);
//                        }
//                    }
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
//            }
//        }
//
//    }

//    @Scheduled(initialDelay=30000, fixedDelay = 1500)   //fixedDelay间隔时间必须执行不管第一条执行多久
    public void task1() {
        System.out.println(DateUtil.formatDateTime(new Date())+"-----task1");
    }
    /**
     * 定时计算。每天凌晨 09:15 执行一次
     */
//    @Scheduled(cron = "0 18 13 * * *")    //间隔多久执行一次 按起始时间来算    如间隔时间5秒  0点开始 任务执行6秒,下一次执行是10秒开始
    public void task2() {
        System.out.println(DateUtil.formatDateTime(new Date())+"-----task2");
    }
//    @Scheduled(cron="0/10 * *  * * ? ")   //每10秒执行一次
    public void task3() {
        System.out.println(DateUtil.formatDateTime(new Date())+"-----task3");
    }

///**
// * 业务通知状态
// */没有人用
//        private String loadStatus;
//
//
///**
// *是否已到EMS服务器同步数据(只对EMS短信节点有效)
// */
//        private String isSynchro;
//
//
//        /**
//         * 短信平台发送返回状态内容
//         */回调时用了
//        private String outResponseMessage;



    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-context-task.xml");
    }
    /*
    一个cron表达式有至少6个（也可能7个）有空格分隔的时间元素。
       按顺序依次为
      1  秒（0~59）
      2  分钟（0~59）
      3 小时（0~23）
      4  天（0~31）
      5 月（0~11）
      6  星期（1~7 1=SUN 或 SUN，MON，TUE，WED，THU，FRI，SAT）
      7.年份（1970－2099）
      其中每个元素可以是一个值(如6),一个连续区间(9-12),一个间隔时间(8-18/4)(/表示每隔4小时),一个列表(1,3,5),通配符。由于"月份中的日期"和"星期中的日期"这两个元素互斥的,必须要对其中一个设置?.
       0 0 10,14,16 * * ? 每天上午10点，下午2点，4点
       0 0/30 9-17 * * ?   朝九晚五工作时间内每半小时
       0 0 12 ? * WED 表示每个星期三中午12点
       "0 0 12 * * ?" 每天中午12点触发
       "0 15 10 ? * *" 每天上午10:15触发
       "0 15 10 * * ?" 每天上午10:15触发
       "0 15 10 * * ? *" 每天上午10:15触发
       "0 15 10 * * ? 2005" 2005年的每天上午10:15触发
       "0 * 14 * * ?" 在每天下午2点到下午2:59期间的每1分钟触发
       "0 0/5 14 * * ?" 在每天下午2点到下午2:55期间的每5分钟触发
       "0 0/5 14,18 * * ?" 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
       "0 0-5 14 * * ?" 在每天下午2点到下午2:05期间的每1分钟触发
       "0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44触发
       "0 15 10 ? * MON-FRI" 周一至周五的上午10:15触发
       "0 15 10 15 * ?" 每月15日上午10:15触发
       "0 15 10 L * ?" 每月最后一日的上午10:15触发
       "0 15 10 ? * 6L" 每月的最后一个星期五上午10:15触发
       "0 15 10 ? * 6L 2002-2005" 2002年至2005年的每月的最后一个星期五上午10:15触发
       "0 15 10 ? * 6#3" 每月的第三个星期五上午10:15触发
       有些子表达式能包含一些范围或列表
       例如：子表达式（天（星期））可以为 “MON-FRI”，“MON，WED，FRI”，“MON-WED,SAT”
       “*”字符代表所有可能的值
       “/”字符用来指定数值的增量
       例如：在子表达式（分钟）里的“0/15”表示从第0分钟开始，每15分钟
                在子表达式（分钟）里的“3/20”表示从第3分钟开始，每20分钟（它和“3，23，43”）的含义一样
       “？”字符仅被用于天（月）和天（星期）两个子表达式，表示不指定值
       当2个子表达式其中之一被指定了值以后，为了避免冲突，需要将另一个子表达式的值设为“？”
       “L” 字符仅被用于天（月）和天（星期）两个子表达式，它是单词“last”的缩写
       如果在“L”前有具体的内容，它就具有其他的含义了。例如：“6L”表示这个月的倒数第６天
       注意：在使用“L”参数时，不要指定列表或范围，因为这会导致问题
       W 字符代表着平日(Mon-Fri)，并且仅能用于日域中。它用来指定离指定日的最近的一个平日。大部分的商业处理都是基于工作周的，所以 W 字符可能是非常重要的。
       例如，日域中的 15W 意味着 "离该月15号的最近一个平日。" 假如15号是星期六，那么 trigger 会在14号(星期五)触发，因为星期四比星期一离15号更近。
       C：代表“Calendar”的意思。它的意思是计划所关联的日期，如果日期没有被关联，则相当于日历中所有日期。例如5C在日期字段中就相当于日历5日以后的第一天。1C在星期字段中相当于星期日后的第一天。
       字段   允许值   允许的特殊字符
       秒           0-59           , - * /
       分           0-59           , - * /
       小时           0-23           , - * /
       日期           1-31           , - * ? / L W C
       月份           1-12 或者 JAN-DEC           , - * /
       星期           1-7 或者 SUN-SAT           , - * ? / L C #
       年（可选）           留空, 1970-2099           , - * /
     */
    /*
    1.initialDelay :初次执行任务之前需要等待的时间
    @Scheduled(initialDelay =5000)
    2.fixedDelay:每次执行任务之后间隔多久再次执行该任务。
    @Scheduled(fixedDelay=5000)
    3.fixedRate:执行频率，每隔多少时间就启动任务，不管该任务是否启动完成
    @Scheduled(fixedRate=5000)
     */

    public ISmsLogInfoService getSmsLogInfoService() {
        return smsLogInfoService;
    }

    public void setSmsLogInfoService(ISmsLogInfoService smsLogInfoService) {
        this.smsLogInfoService = smsLogInfoService;
    }

    public ISupplierPropertyService getSmsSupplierPropertyService() {
        return smsSupplierPropertyService;
    }

    public void setSmsSupplierPropertyService(ISupplierPropertyService smsSupplierPropertyService) {
        this.smsSupplierPropertyService = smsSupplierPropertyService;
    }
}
